home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / progjour / 1991 / 06 / alib / stream.asm < prev    next >
Assembly Source File  |  1991-08-21  |  10KB  |  462 lines

  1.     title    stream i/o
  2.     include    asm.inc
  3.  
  4.     public    fclose
  5.     public    fopen
  6.     public    fread
  7.     public    fwrite
  8.  
  9. SIO_BUFSIZ    equ    8192    ; stream io buffer size
  10.  
  11. stream_io_str struc
  12.   sio_position        dd  ?    ; stream position
  13.   sio_offset        dd  ?    ; buffer offset
  14.   sio_read_bc        dw  ?    ; buffer byte count for reading
  15.   sio_write_bc        dw  ?    ; buffer byte count for writing
  16.   sio_file_handle    dw  ?    ; dos file handle
  17.   sio_buffer        db SIO_BUFSIZ dup(?)  ; stream buffer
  18. stream_io_str ends
  19.  
  20.  
  21.     .data
  22.     extb    ertx_disk_full
  23. ertx_fopen_mode        db    'Bad mode in fopen',0
  24. ertx_out_of_handles    db    'Out of stream handles',0
  25. ertx_stream_handle    db    'Bad stream handle',0
  26.  
  27.     .data?
  28. stream_pointers        dd    FOPEN_MAX dup(?)
  29.  
  30.  
  31.     .code
  32.     extn    free,ms_dos,ms_dos_strerror,set_strerror,malloc
  33.  
  34.  
  35. ;;    fclose
  36. ;
  37. ;    entry    BX    stream handle
  38. ;    exit    Cf    if error closing file or bad handle
  39. ;    uses    AX,BX
  40. ;
  41. fclose    proc
  42.     pushm    di,si,es
  43.     call    fwrite_flush        ; write bytes left in stream buffer
  44.     jc    fcl1            ;  if disk full
  45.  
  46.     call    stream_struct_write    ; access stream structure
  47.     jc    fcl1            ;  if bad handle
  48.  
  49.     mov    si,bx            ; clear stream structure pointer
  50.     add    si,si
  51.     add    si,si
  52.     mov    wptr stream_pointers[bp+si],NULL_POINTER
  53.     mov    wptr stream_pointers[bp+si+2],NULL_POINTER
  54.  
  55.     mov    bx,es:sio_file_handle[di]
  56.     call    free
  57.  
  58.     mov    ah,3Eh
  59.     call    ms_dos_strerror
  60.  
  61. fcl1:    popm    es,si,di
  62.     ret
  63. fclose    endp
  64.  
  65.  
  66. ;;    fopen
  67. ;
  68. ;    entry    AX    mode, 'r' or 'w' to open for reading or writing
  69. ;        DS:SI    filename
  70. ;    exit    BX    stream handle
  71. ;        Cf    if error
  72. ;    uses    AX
  73. ;
  74. fopen    proc
  75.     pushm    cx,dx,di,es
  76.     cmp    ax,'r'
  77.     mov    dx,3D00h
  78.     je    fop1            ; if opening file for reading only
  79.     cmp    ax,'w'
  80.     jne    fop3            ; if not open for write (unknown mode)
  81.     mov    dh,3Ch
  82.     mov    cx,0
  83. fop1:    mov    ax,dx
  84.     mov    dx,si
  85.     call    ms_dos_strerror        ; (ms dos with error handling)
  86.     jc    fop2            ;  if file open failed
  87.     mov    dx,ax
  88.  
  89.     call    malloc_stream
  90.     jc    fop4            ;  if no memory or stream handles
  91.  
  92.     mov    al,0            ; zero stream structure (except for
  93.     mov    cx,sio_buffer        ;  buffer space)
  94.     push    di
  95.     rep    stosb
  96.     pop    di
  97.  
  98.     mov    es:sio_file_handle[di],dx
  99.     clc
  100. fop2:    popm    es,di,dx,cx
  101.     ret
  102.  
  103. fop3:    lea    ax,ertx_fopen_mode    ; *Bad mode in fopen*
  104.     call    set_strerror
  105.     jmp    fop2
  106.  
  107. fop4:    mov    ah,3Eh            ; close file, no memory for structure
  108.     mov    bx,dx
  109.     call    ms_dos
  110.     stc
  111.     jmp    fop2
  112. fopen    endp
  113.  
  114.  
  115. ;;    fread
  116. ;
  117. ;    entry    BX    stream handle
  118. ;        CX    byte count
  119. ;        ES:DI    destination pointer
  120. ;    exit    AX    actual byte count (!=CX for EOF)
  121. ;        DI    updated
  122. ;        Cf    if error
  123. ;
  124. fread    proc
  125.     pushm    di,bx,cx,dx,si,ds
  126.     cmp    bx,stdin
  127.     je    fre3            ; if special handle, standard input
  128.  
  129.     call    stream_struct_read
  130.     jc    fre4
  131.     mov    bx,si
  132.  
  133. fre1:    jcxz    fre4            ; if read finished
  134.  
  135.     mov    ax,wptr sio_position[bx]; compute stream position w/i buffer
  136.     mov    dx,wptr sio_position[bx+2]
  137.     sub    ax,wptr sio_offset[bx]
  138.     sbb    dx,wptr sio_offset[bx+2]
  139.     jnz    fre2            ;  if buffer not w/i 64k of position
  140.  
  141.     mov    dx,sio_read_bc[bx]    ; get number of bytes to end of buffer
  142.     sub    dx,ax
  143.     jbe    fre2            ;  if stream position not in buffer
  144.  
  145.     lea    si,sio_buffer[bx]
  146.     add    si,ax
  147.  
  148.     call    rep_movsb_limit
  149.  
  150.     add    wptr sio_position[bx],dx ; update stream position
  151.     adc    wptr sio_position[bx+2],0
  152.     jmp    fre1
  153.  
  154. fre2:    call    fread_primitive        ; fill stream buffer
  155.     jbe    fre4            ;  if error (Cf==1) or EOF (Zf==1)
  156.     jmp    fre1            ;  else successful
  157.  
  158. fre3:    mov    ah,3Fh            ; read from special handle stdin
  159.     mov    dx,es
  160.     mov    ds,dx
  161.     mov    dx,di
  162.     call    ms_dos_strerror
  163.     jc    fre4
  164.  
  165.     add    di,ax            ; (should not set Cf unless DI wraps)
  166.  
  167. fre4:    popm    ds,si,dx,cx,bx,ax
  168.     jc    fre5            ; if error
  169.     neg    ax            ; else return bytes read
  170.     add    ax,di
  171.     clc
  172. fre5:    ret
  173. fread    endp
  174.  
  175.  
  176. ;;    fread primitive
  177. ;
  178. ;    entry    DS:BX    stream structure
  179. ;    exit    AX    bytes read from file
  180. ;        Cf    if error (Zf unknown)
  181. ;        Zf    if end of file
  182. ;    uses    SI
  183. ;
  184. fread_primitive proc
  185.     pushm    bx,cx,dx
  186.     mov    si,bx
  187.  
  188.     mov    ax,4200h        ; position file
  189.     mov    bx,sio_file_handle[si]
  190.     mov    dx,wptr sio_position[si]
  191.     mov    cx,wptr sio_position[si+2]
  192.     call    ms_dos_strerror
  193.     jc    frp1            ;  if error position file
  194.  
  195.     mov    wptr sio_offset[si],ax
  196.     mov    wptr sio_offset[si+2],dx
  197.     mov    sio_read_bc[si],0
  198.  
  199.     mov    ah,3Fh            ; read file
  200.     mov    cx,size sio_buffer
  201.     lea    dx,sio_buffer[si]
  202.     call    ms_dos_strerror
  203.     jc    frp1            ;  if read error
  204.     mov    sio_read_bc[si],ax
  205.  
  206.     or    ax,ax            ; set Zf for end of file
  207. frp1:    popm    dx,cx,bx
  208.     ret
  209. fread_primitive endp
  210.  
  211.  
  212. ;;    fwrite
  213. ;
  214. ;    entry    BX    stream handle
  215. ;        CX    byte count
  216. ;        DS:SI    source pointer
  217. ;    exit    AX    bytes written
  218. ;        SI    updated
  219. ;        Cf    if error
  220. ;
  221. fwrite    proc
  222.     pushm    si,cx,dx,di,es
  223.     cmp    bx,stdout        ; check for special streams
  224.     je    fwr2            ;  if writing to standard out
  225.     cmp    bx,stderr
  226.     je    fwr2            ;  if writing to standard error
  227.  
  228.     call    fwrite_flush_maybe    ; flush buffer in event of seek
  229.     jc    fwr3            ;  if bad handle or disk full
  230.  
  231.     call    stream_struct_write    ; access stream structure
  232.     jc    fwr3            ;  if bad handle
  233.  
  234. fwr1:    clc
  235.     jcxz    fwr3            ;  if write complete
  236.  
  237.     mov    ax,es:sio_write_bc[di]    ; compute space left in stream buffer
  238.     mov    dx,size sio_buffer
  239.     sub    dx,ax
  240.     jb    fwr3            ;  if internal error (Cf=1)
  241.  
  242.     push    di            ; copy to stream buffer
  243.     lea    di,sio_buffer[di]
  244.     add    di,ax
  245.     call    rep_movsb_limit
  246.     pop    di
  247.  
  248.     add    ax,dx            ; update stream buffer byte count
  249.     mov    es:sio_write_bc[di],ax    ;  and position
  250.     add    wptr es:sio_position[di],dx
  251.     adc    wptr es:sio_position[di+2],0
  252.  
  253.     cmp    ax,size sio_buffer    ; check stream buffer level
  254.     jb    fwr1            ;   if not full
  255.     call    fwrite_flush        ;   else write buffer to disk
  256.     jnc    fwr1            ;     if write successful
  257.     jmp    fwr3            ;     else disk full (Cf=1)
  258.  
  259. fwr2:    mov    ah,40h            ; write standard output/error
  260.     mov    dx,si
  261.     call    ms_dos_strerror
  262.     jc    fwr3            ;  if write failed
  263.     add    si,ax
  264.  
  265. fwr3:    popm    es,di,dx,cx,ax
  266.     jc    fwr4            ; if error
  267.     neg    ax            ; else return bytes written
  268.     add    ax,si
  269.     clc
  270. fwr4:    ret
  271. fwrite    endp
  272.  
  273.  
  274. ;;    fwrite flush
  275. ;
  276. ;    entry    BX    stream handle
  277. ;    exit    Cf    if disk full, bad handle, or other error
  278. ;    uses    AX
  279. ;
  280. fwrite_flush proc
  281.     pushm    bx,cx,dx,si,ds
  282.     call    stream_struct_read
  283.     jc    fwf1            ;  if bad handle
  284.  
  285.     mov    cx,sio_write_bc[si]
  286.     jcxz    fwf1            ;  if buffer empty (nothing to flush)
  287.  
  288.     mov    ax,4200h        ; position file
  289.     mov    bx,sio_file_handle[si]
  290.     mov    dx,wptr sio_offset[si]
  291.     mov    cx,wptr sio_offset[si+2]
  292.     call    ms_dos_strerror
  293.     jc    fwf1            ;  if position failed
  294.  
  295.     mov    ah,40h            ; write file
  296.     mov    cx,sio_write_bc[si]
  297.     lea    dx,sio_buffer[si]
  298.     call    ms_dos_strerror
  299.     jc    fwf1            ;  if write failed
  300.  
  301.     add    wptr sio_offset[si],ax    ; update buffer position
  302.     adc    wptr sio_offset[si+2],0
  303.     mov    sio_write_bc[si],0    ; clear output byte count
  304.  
  305.     cmp    ax,cx
  306.     je    fwf1            ;  if correct byte cnt written (Cf=0)
  307.  
  308.     lea    ax,ertx_disk_full    ;  else *Disk full*
  309.     call    set_strerror
  310.  
  311. fwf1:    popm    ds,si,dx,cx,bx
  312.     ret
  313. fwrite_flush endp
  314.  
  315.  
  316. ;;    fwrite flush maybe
  317. ;
  318. ;    entry    BX    stream handle
  319. ;    exit    Cf    if bad handle or disk full
  320. ;    uses    AX,DX
  321. ;
  322. fwrite_flush_maybe proc
  323.     pushm    si,ds
  324.     call    stream_struct_read
  325.     jc    ffm2            ;  if bad stream handle
  326.  
  327.     mov    ax,wptr sio_offset[si]    ; compute buffer position
  328.     mov    dx,wptr sio_offset[si+2]
  329.     add    ax,sio_write_bc[si]
  330.     adc    dx,0
  331.  
  332.     cmp    ax,wptr sio_position[si]
  333.     jne    ffm1            ;  if wrong position
  334.     cmp    dx,wptr sio_position[si+2]
  335.     je    ffm2            ;  if right position
  336.  
  337. ffm1:    call    fwrite_flush
  338.     jc    ffm2            ;  if disk full
  339.  
  340.     mov    ax,wptr sio_position[si] ; reposition buffer
  341.     mov    wptr sio_offset[si],ax
  342.     mov    ax,wptr sio_position[si+2]
  343.     mov    wptr sio_offset[si+2],ax
  344.  
  345. ffm2:    popm    ds,si
  346.     ret
  347. fwrite_flush_maybe endp
  348.  
  349.  
  350. ;;    malloc stream
  351. ;
  352. ;    exit    BX    stream handle
  353. ;        ES:DI    stream structure
  354. ;        Cf    if no handles or memory left
  355. ;    uses    AX
  356. ;
  357. malloc_stream proc
  358.     pushm    cx,si
  359.     mov    bx,stderr        ; find free stream handle
  360. mas1:    inc    bx
  361.     cmp    bx,FOPEN_MAX
  362.     jae    mas3            ;  if no handles left
  363.  
  364.     mov    si,bx
  365.     add    si,si
  366.     add    si,si
  367.     les    di,stream_pointers[bp+si]
  368.     mov    ax,es
  369.     or    ax,di
  370.     jnz    mas1            ;  if stream allocated
  371.  
  372.     mov    cx,size stream_io_str    ; allocate memory for stream structure
  373.     call    malloc
  374.     jc    mas2            ;  if no memory
  375.  
  376.     mov    wptr stream_pointers[bp+si],di
  377.     mov    wptr stream_pointers[bp+si+2],es
  378.  
  379. mas2:    popm    si,cx
  380.     ret
  381.  
  382. mas3:    lea    ax,ertx_out_of_handles    ; *Out of stream handles*
  383.     call    set_strerror
  384.     jmp    mas2
  385. malloc_stream endp
  386.  
  387.  
  388. ;;    rep movsb limit
  389. ;
  390. ;    entry    DS:SI    source pointer
  391. ;        ES:DI    destination pointer
  392. ;        CX    byte count
  393. ;        DX    byte count limit
  394. ;    exit    SI,DI    updated
  395. ;        CX    updated (nonzero if original DX<CX)
  396. ;        DX    actual number of bytes transfered (minimum of CX,DX)
  397. ;
  398. rep_movsb_limit proc
  399.     push    ax
  400.     cmp    cx,dx            ; DX is unsigned minimum of CX and DX
  401.     ja    rmm1
  402.     mov    dx,cx
  403.  
  404. rmm1:    mov    ax,cx            ; this procedure implements a smart
  405.     sub    ax,dx            ;  "rep movsb" instruction.  the
  406.     mov    cx,dx            ;  difference is it moves the minimum
  407.     rep    movsb            ;  number of bytes specified in CX or
  408.     mov    cx,ax            ;  DX.  CX is updated normally; DX has
  409.     pop    ax            ;  the actual number of bytes moved.
  410.     ret
  411. rep_movsb_limit endp
  412.  
  413.  
  414. ;;    stream struct read
  415. ;
  416. ;    entry    BX    stream handle
  417. ;    exit    DS:SI    stream structure
  418. ;        Cf    if bad handle
  419. ;    uses    AX
  420. ;
  421. stream_struct_read proc
  422.     cmp    bx,FOPEN_MAX
  423.     jae    rss1            ;  if handle too large
  424.     mov    si,bx
  425.     add    si,si
  426.     add    si,si
  427.     lds    si,stream_pointers[bp+si]
  428.     mov    ax,ds
  429.     or    ax,si
  430.     jz    rss1            ;  if inactive stream
  431.     ret
  432.  
  433. rss1:    lea    ax,ertx_stream_handle    ; *Bad stream handle*
  434.     jmp    set_strerror
  435. stream_struct_read endp
  436.  
  437.  
  438. ;;    stream struct write
  439. ;
  440. ;    entry    BX    stream handle
  441. ;    exit    ES:DI    stream structure
  442. ;        Cf    if bad handle
  443. ;    uses    AX
  444. ;
  445. stream_struct_write proc
  446.     cmp    bx,FOPEN_MAX
  447.     jae    wss1            ;  if handle too large
  448.     mov    di,bx
  449.     add    di,di
  450.     add    di,di
  451.     les    di,stream_pointers[bp+di]
  452.     mov    ax,es
  453.     or    ax,di
  454.     jz    wss1            ;  if inactive stream
  455.     ret
  456.  
  457. wss1:    lea    ax,ertx_stream_handle    ; *Bad stream handle*
  458.     jmp    set_strerror
  459. stream_struct_write endp
  460.  
  461.     end
  462.